package com.springboot2.shiro.configuration;

import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * RedisCacheConfiguration
 *
 * @author Archx[archx@foxmail.com]
 * at 2018/7/13 22:13
 */
@Configuration
@EnableCaching
public class RedisCachingConfiguration extends CachingConfigurerSupport {

    private RedisConnectionFactory redisConnectionFactory;

    public RedisCachingConfiguration(RedisConnectionFactory redisConnectionFactory) {
        this.redisConnectionFactory = redisConnectionFactory;
    }

    @Bean
    @Override
    public KeyGenerator keyGenerator() {
        return (target, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(target.getClass().getName());
            sb.append(".").append(method.getName());

            StringBuilder paramsSb = new StringBuilder();
            for (Object param : params) {
                // 如果不指定，默认生成包含到键值中
                if (param != null) {
                    paramsSb.append(param.toString());
                }
            }

            if (paramsSb.length() > 0) {
                sb.append("_").append(paramsSb);
            }
            return sb.toString();
        };
    }

    @Bean
    @Override
    public CacheManager cacheManager() {
        RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
        configuration = configuration.serializeValuesWith(RedisSerializationContext.SerializationPair
                                                                  .fromSerializer(new GenericFastJsonRedisSerializer()));
        configuration = configuration.computePrefixWith(cacheName -> cacheName + ":");

        return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(configuration).build();
    }

    @Bean
    public RedisTemplate<String, Object> redisTemplate() {
        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(redisConnectionFactory);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new GenericFastJsonRedisSerializer());
        return template;
    }

}
